<template>
  <a-form
    class="lg-form"
    :model="searchParam"
    ref="ruleFormRef"
    name="validate_other"
    :rules="rule"
    v-bind="formItemLayout"
    @finishFailed="onFinishFailed"
    @finish="onFinish"
  >
    <a-row :gutter="24">
      <template v-for="item in getFormList" :key="item.prop">
        <a-col
          :span="item.span ? item.span:spanNum"
          v-if="!hiddenRule[item.prop] || hiddenRule[item.prop](searchParam)"
        >
          <a-form-item :name="item.prop" v-bind="item.rules? {rules:item.rules }:{}" has-feedback>
            <template #label>
              <slot name="title" v-bind="item" v-if="hasSlot('title')"></slot>
              <span v-else>{{ item.label }} </span>
            </template>

            <!-- 文本框 -->
            <slot
              :name="item.prop"
              v-bind="{ searchParam, item }"
              v-if="hasSlot(item.prop)"
            ></slot>
            <template v-else>
              <template v-if="item.type == undefined || item.type == 'text'">
                <a-input
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="t('config.required')"
                  v-bind="item.searchProps"
                  allow-clear
                >
                </a-input>
              </template>

              <!-- 下拉输入 -->
              <template v-if="item.type == 'complete'">
                <a-auto-complete
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="t('config.required')"
                  :filter-option="filterOption"
                  v-bind="item.searchProps"
                  allow-clear
                >
                </a-auto-complete>
              </template>

              <!-- 密码框 -->
              <template v-if="item.type == 'password'">
                <a-input-password
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="t('config.required')"
                  v-bind="item.searchProps"
                  allow-clear
                />
              </template>

              <!-- 数字输入框 -->
              <template v-if="item.type == 'number'">
                <a-input-number
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="t('config.required')"
                  v-bind="item.searchProps"
                  allow-clear
                />
              </template>

              <!-- 下拉筛选 -->
              <template v-if="item.type == 'select'">
                <a-select
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="$t('config.select')"
                  v-bind="item.searchProps"
                  allow-clear
                >
                  <a-select-option
                    v-for="itemValue in item.enum"
                    :key="itemValue.value"
                    :value="itemValue.value"
                    :disabled="itemValue.disabled"
                    > {{ itemValue.locale? itemValue.locale[locale]:itemValue.label }}</a-select-option
                  >
                </a-select>
              </template>

              <!-- 开关 -->
              <template v-if="item.type == 'switch'">
                <a-switch
                  v-model:checked="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                />
              </template>

              <!-- 滑动输入条 -->
              <template v-if="item.type == 'slider'">
                <a-slider
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                />
              </template>

              <!-- 单选 -->
              <template v-if="item.type == 'radio'">
                <a-radio-group
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                >
                  <a-radio
                    v-for="itemValue in item.enum"
                    :key="itemValue.value"
                    :disabled="itemValue.disabled"
                    :value="itemValue.value"
                  >
                    {{ itemValue.locale? itemValue.locale[locale]:itemValue.label }}
                  </a-radio>
                  
                </a-radio-group>
              </template>

              <!-- 多选 -->
              <template v-if="item.type == 'checkbox'">
                <a-checkbox-group
                  style="width: 100%"
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                >
                  <!-- <a-row>
                    <a-col
                      :span="item?.searchProps?.span || 8"
                      
                    >
                      
                    </a-col>
                  </a-row> -->
                  <a-checkbox
                        v-for="itemValue in item.enum"
                        :key="itemValue.value"
                        :value="itemValue.value"
                        :disabled="itemValue.disabled"
                        style="line-height: 32px"
                      >
                        {{ itemValue.locale? itemValue.locale[locale]:itemValue.label }}
                      </a-checkbox>
                </a-checkbox-group>
              </template>

              <!-- 评分 -->
              <template v-if="item.type == 'rate'">
                <a-rate
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                  allow-half
                />
              </template>

              <!-- 日期选择器 -->
              <template v-if="item.type == 'date'">
                <a-date-picker
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                  valueFormat="YYYY-MM-DD"
                >
                </a-date-picker>
              </template>

              <!-- 日期选择器时间段 -->
              <template v-if="item.type == 'rangeDate'">
                <a-range-picker
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                  valueFormat="YYYY-MM-DD"
                >
                </a-range-picker>
              </template>

              <!-- 时间选择器 -->
              <template v-if="item.type == 'time'">
                <a-time-picker
                  v-model:value="searchParam[item.prop!]"
                  v-bind="item.searchProps"
                />
              </template>

              <!-- 树形选择 -->
              <template v-if="item.type == 'treeSelect'">
                <a-tree-select
                  v-model:value="searchParam[item.prop!]"
                  style="width: 100%"
                  :tree-data="item.enum"
                  allow-clear
                  :show-checked-strategy="SHOW_PARENT"
                  :placeholder="$t('config.select')"
                  :field-names="FiledName"
                  v-bind="item.searchProps"
                >
                <template #title="field:any">
                  {{ field.locale ? field.locale[locale]:field.label  }}
                </template>
                </a-tree-select>
              </template>

              <!-- 多行文本域 -->
              <template v-if="item.type == 'textarea'">
                <a-textarea
                  v-model:value="searchParam[item.prop!]"
                  :placeholder="t('config.required') "
                  :auto-size="{ minRows: 2, maxRows: 5 }"
                  v-bind="item.searchProps"
                />
              </template>

              <!-- 上传文件 -->
              <template v-if="item.type == 'upload'">
                <a-form-item name="dragger" no-style>
                  <a-upload
                    v-model:fileList="searchParam[item.prop!]"
                    v-bind="item.searchProps"
                    name="files"
                  >
                    <a-button>
                      <template #icon><UploadOutlined /></template>
                      {{ t('config.upload')}}
                    </a-button>
                  </a-upload>
                </a-form-item>
              </template>
            </template>
          </a-form-item>
        </a-col>
      </template>
    </a-row>

    <a-form-item
      :wrapper-col="{ span: 24 }"
      justify="center"
      v-if="showButton"
    >
      <div class="flex">
        <a-button type="primary" html-type="submit">{{ t('config.search') }}</a-button>
        <a-button style="margin-left: 10px" @click="reset(ruleFormRef)">{{
        t('config.reset')
        }}</a-button>
      </div>
    </a-form-item>
  </a-form>
</template>
<script lang="ts">
import './style/index.less';
import { useI18n } from 'vue-i18n'
import useForm from './useForm';
import useFormc from './useformc';
import {
  defineComponent,
  PropType,
  computed,
  ref,
  ExtractPropTypes,
  ComponentPublicInstance,
  watch
} from 'vue';
import type { FormInstance as FormInstanceAnt } from 'ant-design-vue';
import type { Rule } from 'ant-design-vue/es/form';
import type { ConfigureType, NamePath } from './types';
import {debounce} from "lodash";

import {
  DatePicker,
  Button,
  Form,
  Row,
  Col,
  FormItem,
  Input,
  InputNumber,
  Select,
  SelectOption,
  Switch,
  Slider,
  RadioGroup,
  Radio,
  Checkbox,
  CheckboxGroup,
  Rate,
  RangePicker,
  TimePicker,
  TreeSelect,
  Textarea,
} from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';

export type FormExpose = {
  clearValidate: (nameList?: NamePath[]) => void;
  resetFields: (nameList?: NamePath[]) => void;
  validate: (nameList?: NamePath[]) => Promise<any>;
  validateFields: (nameList?: NamePath[]) => Promise<any>;
  resetForm:()=>void;
  updateFormByKey:(key:string,value:any)=>void
};

export const formProps = () => ({
  configure: { type: Array as PropType<ConfigureType[]>, required: true },
  initParam: { type: Object, default: Object },
  layout: { type: Array as PropType<number[]>, default: [6, 14] },
  showButton: { type: Boolean, default: true },
  uselayout: { type: Boolean, default: true },
  colNum: { type: Number, default: 1 },
  isvalidate: { type: Boolean, default: true },
  validate: { type: Object as PropType<Record<string, Rule[]>>, default: Object },
  hiddenRule: {
    type: Object as PropType<Record<string, (params: any) => boolean>>,
    default: Object,
  },
});

export type FormProps = Partial<ExtractPropTypes<ReturnType<typeof formProps>>>;

export type FormInstance = ComponentPublicInstance<FormProps, FormExpose>;

const LgForm = defineComponent({
  name: 'pro-form',
  props: formProps(),
  useForm,
  components: {
    AButton: Button,
    AForm: Form,
    ARow: Row,
    ACol: Col,
    AFormItem: FormItem,
    AInput: Input,
    ADatePicker: DatePicker,
    AInputNumber: InputNumber,
    ASelect: Select,
    ASelectOption: SelectOption,
    ASwitch: Switch,
    ASlider: Slider,
    ARadioGroup: RadioGroup,
    ARadio: Radio,
    ACheckbox: Checkbox,
    ACheckboxGroup: CheckboxGroup,
    ARate: Rate,
    ARangePicker: RangePicker,
    ATimePicker: TimePicker,
    ATreeSelect: TreeSelect,
    ATextarea: Textarea,
    UploadOutlined,
  },
  setup(props, { emit, slots,expose }) {
    const { searchParam, searchInitParam, reset,setSearch } = useFormc();

    const { t,locale } = useI18n({inheritLocale: true,useScope: 'local'})

    const FiledName = ref({
      children: 'children',
      label: 'label',
      value: 'value',
    });

    const ruleFormRef = ref<FormInstanceAnt>();
    const { SHOW_PARENT } = TreeSelect;
    const spanNum = computed(() => Math.ceil(24 / props.colNum));


    // 获取表单列表项
    const getFormList = computed(() => {
      return props.configure
    });
    
    // 设置搜索表单的默认值
    props.configure.forEach((column) => {
      if (
        column.searchInitParam !== undefined &&
        column.searchInitParam !== null
      ) {
        // 此行注释不要删除
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        searchInitParam.value[column.prop!] = column.searchInitParam;
      }
    });

    // 表单验证规则
    const rule = computed(() => {
      if (props.isvalidate) {
        return props.validate;
      }
      return {};
    });


    const emitSearchParam = ()=>{
      emit("onSearchParam",searchParam.value)
    }

    const debounceOnSearchParam = debounce(emitSearchParam,200)

    watch(()=>searchParam.value,()=>{
      debounceOnSearchParam()
    },{immediate:true,deep:true})

    const formItemLayout = {
      labelCol: props.uselayout ? { span: props.layout[0] || 6 } : {},
      wrapperCol: props.uselayout ? { span: props.layout[1] || 14 } : {},
    };

    const onFinishFailed = (errorInfo: any) => {
      try {
        emit('onFinishFailed', errorInfo);
      } catch (error) {
        console.log('表单提交出错', error);
      }
    };

    const onFinish = async (values: any) => {
      try {
        emit('onFinish', values);
      } catch (error) {
        onFinishFailed(error);
      }
    };

    const filterOption = (input: string, option: any) => {
      return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0;
    };


    const clearValidate = ()=>ruleFormRef.value.clearValidate()
    const resetFields = ()=>ruleFormRef.value.resetFields()
    const validate = ()=>ruleFormRef.value.validate()
    const validateFields = ()=>ruleFormRef.value.validateFields()
    const resetForm = ()=> reset(ruleFormRef.value)
    const updateFormByKey = (key:string,value:any)=>setSearch(key,value)

    // 导出父组件可直接调用方法
    expose({ clearValidate, resetFields, validate, validateFields,resetForm,updateFormByKey });
    const hasSlot = (name) => !!slots[name];

    return {
      spanNum,
      SHOW_PARENT,
      ruleFormRef,
      getFormList,
      FiledName,
      rule,
      searchParam,
      searchInitParam,
      formItemLayout,
      reset,
      onFinishFailed,
      onFinish,
      hasSlot,
      filterOption,
      t,
      locale
    };
  },
});

export default LgForm as typeof LgForm & {
  readonly useForm: typeof useForm;
};
</script>
